package com.idanchuang.component.logback.converter;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.pattern.MessageConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.idanchuang.component.logback.config.LogbackCryptConfig;
import com.idanchuang.component.logback.enums.MaskType;
import com.idanchuang.component.logback.config.LogbackMaskConfig;
import com.idanchuang.component.logback.helper.LogContext;
import com.idanchuang.component.logback.util.LogConvertUtil;
import com.idanchuang.component.logback.util.LogUtil;
import com.idanchuang.component.logback.util.LogbackCryptUtil;

import java.util.Arrays;

public class MaskMessageConverter extends MessageConverter {

    private static LogbackMaskConfig logbackMaskConfig;

    @Override
    public String convert(ILoggingEvent iLoggingEvent) {
        // 如果是组件内部log, 则直接跳过
        if (LogContext.INTERNAL_LOGGER_NAME.equals(iLoggingEvent.getLoggerName())) {
            return super.convert(iLoggingEvent);
        }
        boolean isRollingFileAppender = LogConvertUtil.isRollingFileAppender();
        MaskType[] ignoreMaskTypes = isRollingFileAppender ? LogContext.removeIgnoreMasks() : LogContext.getIgnoreMasks();
        boolean keepOriginLog = isRollingFileAppender ? LogContext.removeKeepOrigin() : LogContext.getKeepOrigin();
        // debug 及以下级别不做脱敏
        if (iLoggingEvent.getLevel().levelInt <= Level.DEBUG_INT) {
            return super.convert(iLoggingEvent);
        }
        if (logbackMaskConfig == null || !logbackMaskConfig.isEnabled()) {
            return super.convert(iLoggingEvent);
        }
        if (ignoreMaskTypes != null && ignoreMaskTypes.length == 1 && ignoreMaskTypes[0].equals(MaskType.PATTERN_ALL)) {
            return super.convert(iLoggingEvent);
        }
        String message = super.convert(iLoggingEvent);
        if (message == null) {
            return null;
        }
        String maskMessage = doMask(message, ignoreMaskTypes);
        if ((logbackMaskConfig.isKeepOrigin() || keepOriginLog) && !message.equals(maskMessage)) {
            LogbackCryptConfig config = LogbackCryptConfig.getInstance().orElse(null);
            if (config == null) {
                maskMessage += " " + message;
            } else {
                String originMessage = LogbackCryptUtil.encrypt(message, config);
                maskMessage += " " + originMessage;
            }
        }
        return maskMessage;
    }

    private static String doMask(String message, MaskType[] ignoreMaskTypes) {
        if (logbackMaskConfig.isMaskMobile() && !isIgnore(ignoreMaskTypes, MaskType.MOBILE)) {
            message = LogUtil.maskMobileAuto(message);
        }
        if (logbackMaskConfig.isMaskIdCard() && !isIgnore(ignoreMaskTypes, MaskType.ID_CARD)) {
            message = LogUtil.maskIdCardAuto(message);
        }
        if (logbackMaskConfig.isMaskBankNumber() && !isIgnore(ignoreMaskTypes, MaskType.BANK_NUMBER)) {
            message = LogUtil.maskBankNumberAuto(message);
        }
        if (logbackMaskConfig.isMaskEmail() && !isIgnore(ignoreMaskTypes, MaskType.EMAIL)) {
            message = LogUtil.maskEmailAuto(message);
        }
        if (logbackMaskConfig.isMaskAkSk() && !isIgnore(ignoreMaskTypes, MaskType.AK_SK)) {
            message = LogUtil.maskAKSKAuto(message);
        }
        if (logbackMaskConfig.isMaskCustom() && !isIgnore(ignoreMaskTypes, MaskType.CUSTOM)) {
            // custom
            if (logbackMaskConfig.getCustomMasks() != null && !logbackMaskConfig.getCustomMasks().isEmpty()) {
                for (String key : logbackMaskConfig.getCustomMasks().keySet()) {
                    message = LogUtil.maskCustom(message, key, logbackMaskConfig.getCustomMasks().get(key));
                }
            }
        }
        return message;
    }

    public static void setLogbackMaskConfig(LogbackMaskConfig logbackMaskConfig) {
        MaskMessageConverter.logbackMaskConfig = logbackMaskConfig;
    }


    private static boolean isIgnore(MaskType[] ignoreMaskTypes, MaskType maskType) {
        if (ignoreMaskTypes == null || ignoreMaskTypes.length == 0) {
            return false;
        }
        return Arrays.asList(ignoreMaskTypes).contains(maskType);
    }

//
//    public static void main(String[] args) {
//        MaskMessageConverter.logbackMaskConfig = new LogbackMaskConfig();
//        logbackMaskConfig.setEnabled(true);
//        logbackMaskConfig.setKeepOrigin(true);
//        logbackMaskConfig.setMaskAkSk(true);
//        logbackMaskConfig.setMaskEmail(true);
//        logbackMaskConfig.setMaskMobile(true);
//        logbackMaskConfig.setMaskBankNumber(true);
//        logbackMaskConfig.setMaskIdCard(true);
//        String[] messages = {
//                "随便写一串数字: 32971248934590453268959862980215734@658217-68214231460325983745983593, " +
//                        "手机号: +8615089564583, 简写手机号: 15089564583, " +
//                        "身份证号: 330492198812244721, 身份证号2: 33049219881224472x, " +
//                        "银行卡号: 491648411333978312, 银行卡号2: 4916484113339783128, 信用卡号: 4916484113339780, " +
//                        "邮箱: 192@aliyun.com, 邮箱2: yangjiayi@accesscorporate.com.cn, " +
//                        "AKID: rDhc9qxjhIhlBiyphP7buo5yg5h6Eq" +
//                        ", AKKEY: XQr1EPtfnlZLYlQc",
//                "32971248934590453268959862980215734@658217-68214231460325983745983593",
//                "+8615089564583",
//                "15089564583",
//                "330492198812244721",
//                "33049219881224472x",
//                "491648411333978312",
//                "4916484113339783128",
//                "4916484113339780",
//                "192@aliyun.com",
//                "yangjiayi@accesscorporate.com.cn",
//                "rDhc9qxjhIhlBiyphP7buo5yg5h6Eq",
//                "XQr1EPtfnlZLYlQc",
//                System.currentTimeMillis()+"",
//                new Date().toString()
//        };
//        for (String message : messages) {
//            String origin = message;
//            message = doMask(message, null);
//            System.out.println(origin);
//            System.out.println(message + " " + LogbackCryptUtil.encrypt(message, new LogbackCryptConfig()));
//        }
//    }

}
